﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
 
namespace Entity
{
    /// <summary>
    /// IQueryable扩展
    /// </summary>
    public static class LinqEntity
    {
        /// <summary>
        /// 获取对应的字段名
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="keySelector"></param>
        /// <returns></returns>
        public static string GetMemberName<TSource, TKey>(Expression<Func<TSource, TKey>> keySelector)
        {
            string fieldName = null;
            var exp = keySelector.Body as UnaryExpression;
            if (exp == null)
            {
                var body = keySelector.Body as MemberExpression;
                fieldName = body.Member.Name;
            }
            else
            {
                fieldName = (exp.Operand as MemberExpression).Member.Name;
            }
            return fieldName;
        }

        /// <summary>
        /// linq结果集根据PredicateList条件构造者去过滤集合
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="linq"></param>
        /// <param name="predicateList"></param>
        /// <returns></returns>
        public static IQueryable<TEntity> LinqForPredicate<TEntity>(this IQueryable<TEntity> linq, PredicateList<TEntity> predicateList) where TEntity : class
        {
            if (predicateList != null)
            {
                if (predicateList.Count() > 0)
                    predicateList.ToList().ForEach(i =>
                    {
                        linq = linq.Where(i);
                    });
                if (predicateList.OrderList.Count > 0)
                    predicateList.OrderList.ToList().ForEach(i =>
                    {
                        linq = linq.OrderBy(i.Key, i.Value);
                    });

            }
            return linq;
        }

        /// <summary>
        /// 排序
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="propertyName">属性名称</param>
        /// <param name="ascending">是否递增asc</param>
        /// <returns></returns>
        static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName, bool ascending) where T : class
        {
            Type type = typeof(T);

            PropertyInfo property = type.GetProperty(propertyName);
            if (property == null)
                throw new ArgumentException("propertyName", "Not Exist");

            ParameterExpression param = Expression.Parameter(type, "p");
            Expression propertyAccessExpression = Expression.MakeMemberAccess(param, property);
            LambdaExpression orderByExpression = Expression.Lambda(propertyAccessExpression, param);

            string methodName = ascending ? "OrderBy" : "OrderByDescending";

            MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName, new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExpression));

            return source.Provider.CreateQuery<T>(resultExp);
        }
        /// <summary>
        /// 排序（递增asc）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName) where T : class
        {
            return OrderBy<T>(source, propertyName, true);
        }


    }
}
